﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;
using System.Threading;
using FinPlusAssembler;
using FinPlusInterfaces;

namespace FinPlusCompView
{
    public partial class FinPlusPodEditor : FinPlusControl
    {
        [State(Test = true)]
        public override bool IsValid { get; set; }
        [State(Save = true, Test = true)]
        public string ColumnState { get { return _colHelper.GetColState(dataGrid); } set { _colHelper.SetColState(dataGrid, _colSelectBar, value); } }

        public override IPods Adapter { get { return base.Children(colSelectotGrid.Children); } }
        
        private enum Params { Tag }
        private enum Cols { Id, Name, Value, TimeStamp, User, Type }
        private IConnDatabase _conn;
        private CollectionViewSource _viewSource;
        private readonly SynchronizationContext _context;
        private readonly FinPlusColSelectBar _colSelectBar;
        private readonly FinPlusGridColHelper _colHelper;
        private readonly FinPlusWindow _window;
        private IPod _copy, _pod;

        //construct
        public FinPlusPodEditor(IConnDatabase conn, IPod pod, FinPlusWindow window, FinPlusColSelectBar colSelectBar, FinPlusGridColHelper colHelper, string name, Env env = Env.unknown)
        {
            InitializeComponent();
            _conn = conn;
            _window = window;
            Config = Id = name;
            Env = env;

            _colSelectBar = colSelectBar;
            _colSelectBar.ColSelection += Col_OnSelection;
            _colHelper = colHelper;
            _context = SynchronizationContext.Current;
           
            colSelectotGrid.Children.Add(_colSelectBar);

            foreach (string col in Enum.GetNames(typeof(Cols)))
                _colSelectBar.AddButton(col, false);

            foreach (var col in dataGrid.Columns)
                col.SetValue(TagProperty, col.Header);

            statusBar.Children.Add(new FinPlusStatusBar());

            Set(pod);
        }

        //common control interface
        public override void CmdExecute(IPod command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.Save: Save(); break;
                    case Cmds.Close: Close(); break;
                    case Cmds.Change: Change(command[Params.Tag.ToString()].ToString()); break;
                    case Cmds.Undo: Undo(); break;
                    case Cmds.Loaded: Refresh(); break;
                    case Cmds.ColSelection: AddColSelection(command[Params.Tag.ToString()].ToString()); break;
                    default: throw new Exception(string.Format("cmd not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = Level.Warning.Log(Id, Config, e.Message, e);
            }
        }

        //private
        private void Set(IPod pod)
        {
            _pod = pod;
            _pod.BeanUpdate += (s, a) => this.Dispatcher.Invoke(() => Item_Update(s, a));
            _copy = _pod.Clone(_pod.Id);
            _viewSource = new CollectionViewSource() { Source = _pod };
            _viewSource.SortDescriptions.Clear();
            _viewSource.SortDescriptions.Add(new SortDescription("Index", ListSortDirection.Ascending));
            
            dataGrid.ItemsSource = _viewSource.View;
            SetBooker();

            IsValid = true;
        }

        private void AddSelectBox(DataGridCell cell, IList<string> list)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueSelectBox));
            tb.SetValue(FinPlusValueSelectBox.IdProperty, _pod.Id.ToString());
            tb.SetValue(FinPlusValueSelectBox.ValueProperty, _pod.Name);
            tb.SetValue(FinPlusValueSelectBox.IsEnabledProperty, true);
            tb.SetValue(FinPlusValueSelectBox.ItemSourceProperty, list);
            tb.SetBinding(FinPlusValueSelectBox.TextProperty, new Binding("Value") { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });

            var dt = new ControlTemplate() { VisualTree = tb };
            cell.Template = dt;
        }

        private void AddColSelection(string name)
        {
            var col = dataGrid.Columns.Where(c => c.GetValue(TagProperty).ToString().Equals(name)).First();
            col.Visibility = col.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
        }

        private void Save()
        {
            if (_conn == null)
                _conn = IOC.New<IConnDatabase>();
            _copy = _pod.Clone(_pod.Id);
            _conn.Save(_pod);
            SetBooker();
            Refresh();
        }

        private void Undo()
        {
            _pod = _copy.Clone(_copy.Id);
            Set(_pod);
            Refresh();
        }

        private void Close()
        {
            var r = MessageBox.Show("Do you want to remove pod", "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (r != MessageBoxResult.Yes) 
                return;
            if (_conn == null) 
                _conn = IOC.New<IConnDatabase>();
            var res = _conn.Close(_pod);
            SetBooker();
            Refresh();
        }

        private void Change(string index)
        {
            if (!_pod[index].ToString().Equals(_copy))
                _pod.Get(index).TimeStamp = DateTime.MinValue;
          
            SetBooker();
        }

        private void SetBooker()
        {
            if (_pod == null)
            {
                SetTitle("Unbooked");
                bSave.Visibility = Visibility.Visible;
                bClose.Visibility = bAmend.Visibility = Visibility.Collapsed;
            }
            else if (_pod.Id < 0)//new trade
            {
                SetTitle("Unbooked");
                bSave.Visibility = Visibility.Visible;
                bClose.Visibility = bAmend.Visibility = Visibility.Collapsed;
            }
            else if (_pod.IsClosed)//closed trade
            {
                SetTitle(string.Format("{0} (Id {1}) Removed", _pod.Name, _pod.Id.ToString()));
                dataGrid.IsEnabled = false;
                bUndo.Visibility = bSave.Visibility = bClose.Visibility = bAmend.Visibility = Visibility.Collapsed;
            }
            else //saved trade
            {
                SetTitle(string.Format("{0} (Id {1})", _pod.Name, _pod.Id.ToString()));
                bSave.IsEnabled = false;
                bSave.Visibility = Visibility.Collapsed;
                bClose.Visibility = bAmend.Visibility = Visibility.Visible;
            }
            bUndo.Visibility = _pod.IsEqual(_copy) ? Visibility.Collapsed : Visibility.Visible;
        }

        private void SetTitle(string value)
        {
            _window.SetTitle(value);
        }

        private void Refresh()
        {
            _viewSource.View.Refresh();
            for (int row = 0; row < dataGrid.Items.Count; row++)
            {
                var name = ((TextBlock)dataGrid.GetCell(row, 1).Content).Text;
                var cell = dataGrid.GetCell(row, 2);
                var list = Structure.ToList(name);

                if (name.EnumIsDefined<PodField>())
                    cell.IsEnabled = false;
                else if (list.Count > 0)
                    AddSelectBox(cell, list);
            }
        }

        //cmds
        private enum Cmds { Save, Close, Undo, Change, Loaded, ColSelection }

        //events
        private void Grid_Loaded(object s, RoutedEventArgs a) { CmdRouter(Cmds.Loaded.ToString()); } 
        private void Item_Update(object s, BeanEventArgs a) { CmdRouter(Cmds.Change.ToString(), a.Bean.Name); }
        private void Col_OnSelection(object s, IPod pod) { CmdExecute(pod); }
    }
}
